package com.lzw.crash;
import android.os.*;
import android.content.*;
import java.io.*;
import java.text.*;
import java.util.*;
import android.content.pm.*;
import android.widget.*;
import android.util.*;
import android.app.*;
import android.view.*;
public class mCrash implements Thread.UncaughtExceptionHandler
{

    //文件夹目录
    private static final String PATH = myApp.getContext().getExternalCacheDir().getPath() + "/crash/";
    //文件名
    private static final String FILE_NAME = "crash";
    //文件名后缀
    private static final String FILE_NAME_SUFFIX = ".trace";
    //上下文
    private Context mContext;

    //单例模式
    private static mCrash sInstance = new mCrash();
    private mCrash()
	{}
    public static mCrash getInstance()
	{
        return sInstance;
    }

    /**
     * 初始化方法
     *
     * @param context
     */
    public void init(Context context)
	{
        //将当前实例设为系统默认的异常处理器
        Thread.setDefaultUncaughtExceptionHandler(this);
        //获取Context，方便内部使用
        mContext = context;
    }

    /**
     * 捕获异常回掉
     *
     * @param thread 当前线程
     * @param ex     异常信息
     */
    @Override
    public void uncaughtException(Thread thread, Throwable ex)
	{
        //导出异常信息到SD卡
        dumpExceptionToSDCard(ex);
        //上传异常信息到服务器
        uploadExceptionToServer(ex);

		//显示错误提示框
		new Thread(new ExceptionThread(ex)).start();
    }

    /**
     * 导出异常信息到SD卡
     *
     * @param ex
     */
    private void dumpExceptionToSDCard(Throwable ex)
	{
        if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED))
		{
            return;
        }
        //创建文件夹
        File dir = new File(PATH);
        if (!dir.exists())
		{
            dir.mkdirs();
        }
        //获取当前时间
        long current = System.currentTimeMillis();
        String time = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss").format(new Date(current));
        //以当前时间创建log文件
        File file = new File(PATH + FILE_NAME + time + FILE_NAME_SUFFIX);
		try
		{
			if (!file.exists())
				file.createNewFile();
		}
		catch (IOException e)
		{}
        try
		{
            //输出流操作
			PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter(file)));
			FileOutputStream fo = new FileOutputStream(file);
            //导出手机信息和异常信息
            PackageManager pm = mContext.getPackageManager();
            PackageInfo pi = pm.getPackageInfo(mContext.getPackageName(), PackageManager.GET_ACTIVITIES);
			pw.println("发生异常时间：" + time);
			pw.println("应用版本：" + pi.versionName);
			pw.println("应用版本号：" + pi.versionCode);
			pw.println("android版本号：" + Build.VERSION.RELEASE);
			pw.println("android版本号API：" + Build.VERSION.SDK_INT);
			pw.println("手机制造商:" + Build.MANUFACTURER);
			pw.println("手机型号：" + Build.MODEL);
			ex.printStackTrace(pw);
            //关闭输出流
            pw.close();
        }
		catch (Exception e)
		{
			e.printStackTrace();
        }
    }

    /**
     * 上传异常信息到服务器
     *
     * @param ex
     */
    private void uploadExceptionToServer(Throwable ex)
	{
		String e = ex.getMessage();
    }
	private void restartApp()
	{
        Intent intent = new Intent(myApp.getContext(),
								   MainActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_CLEAR_TASK);
        PendingIntent restartIntent = PendingIntent.getActivity(myApp.getContext(), 0, intent, PendingIntent.FLAG_ONE_SHOT);
        //重启应用
        AlarmManager mgr = (AlarmManager) myApp.getContext().getSystemService(Context.ALARM_SERVICE);
        mgr.set(AlarmManager.RTC, System.currentTimeMillis(), restartIntent);

        //清空Activity栈,防止系统自动重启至崩溃页面,导致崩溃再次出现.
        ActivityManager am = (ActivityManager) myApp.getContext().getSystemService(Context.ACTIVITY_SERVICE);

        //退出程序
        android.os.Process.killProcess(android.os.Process.myPid());
        System.exit(0);
        System.gc();
    }

	/*
     *启动线程弹出对话框
     */
    class ExceptionThread implements Runnable
	{

        private Throwable ex;
		private String execption;
        public ExceptionThread(Throwable ex)
		{
            this.ex = ex;

			Writer writer = new StringWriter();
            PrintWriter printWriter = new PrintWriter(writer);
            ex.printStackTrace(printWriter);
            Throwable cause = ex.getCause();
            while (cause != null)
			{
                cause.printStackTrace(printWriter);
                cause = cause.getCause();
            }
            printWriter.close();
			this.execption = writer.toString();
        }
        @Override
        public void run()
		{
            // TODO: Implement this method
			Looper.prepare();
            showErrorDialog("崩溃日志\n" + execption);
			//Home
			Intent home = new Intent(Intent.ACTION_MAIN);
			home.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
			home.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 
			home.addCategory(Intent.CATEGORY_HOME);
			mContext.startActivity(home);
            Looper.loop();
        }

		
        //打开错误对话框
        public void showErrorDialog(String msg)
		{
            //创建对话框
            Dialog alertDialog = new AlertDialog.Builder(mContext, android.R.style.Theme_Holo_Light_Dialog)
                .setIcon(android.R.drawable.stat_sys_warning)
                .setTitle("程序出错了！")
                .setMessage(msg)
                .setCancelable(true)
                .setPositiveButton("重启应用", new DialogInterface.OnClickListener(){

                    @Override
                    public void onClick(DialogInterface dialog, int which)
					{
                        // TODO: Implement this method
                        dialog.dismiss();
						restartApp();
                    }

                })
                .setNegativeButton("退出", new DialogInterface.OnClickListener(){

                    @Override
                    public void onClick(DialogInterface dialog, int which)
					{
                        // TODO: Implement this method
                        dialog.dismiss();
                        android.os.Process.killProcess(android.os.Process.myPid());
                        System.exit(0);
                    }

                }).create();
            Window window = alertDialog.getWindow();
            WindowManager.LayoutParams attributes = window.getAttributes();
            attributes.type = WindowManager.LayoutParams.TYPE_TOAST;       
            window.setAttributes(attributes);
			try
			{
				alertDialog.show();
			}
			catch (Exception e)
			{
				e.printStackTrace();
			}
		}

	}}
